#pragma once
//
// Created by xietianqi on 2025/1/12.
//
#include "../../Common.h"

/**
 * 结构是hash筒和thread cache的结构相同这个地方是筒锁
 * 挂载的是span是一个管理大块内存的对象存储页一个页或多个页的跨度
 * 不同的是hash筒中8Byte位置的下挂的span被切成了8Byte的多个小块挂在span下
 *           -- nByte位置的下挂的span被切成了nByte的若干小块挂在span下
 *
 * 8字节的span假设是一页,可以切1000个小块,不可以一次性给一个thread cache太多
 * 一个span申请完了找他链表的下一个span 这就导致多线程情况下某个span里面的小块有可能是空的
 * span链表是一个双向链表, 要去归还 page cache 设计成带头双向循环链表
 *
 * 使用单例模式存储central cache 使用饿汉模式实现
 */
class CentralCache {
public:
    static CentralCache *getInstance() { // 单例饿汉
        return &_cacheInstance;
    }

    CentralCache(const CentralCache &centralCache) = delete; //禁用拷贝构造
    CentralCache operator=(const CentralCache &centralCache) = delete;//禁用赋值

    /**
     * 从central cache取对象使用参数来接收目标值
     * @param start 返回链表头
     * @param end   返回链表尾
     * @param batchNum 一批小块的个数
     * @param size 一个小块的大小
     * @return 实际拿到了一小批的个数
     */
    size_t FetchRangeObj(void *&start, void *&end, size_t batchNum, size_t size);
    /**
     * 获取一个非空的span
     * @param list span 链表
     * @param size
     * @return 一个span
     */
    Span* GetOneSpan(SpanList &list, size_t size);

    /**
     * 归还ThreadCache的一部分自由链表给span
     * @param start 自由链表起点
     * @param size 一个节点的大小
     */
    void ReleaseListToSpans(void *start, size_t size);

private:
    CentralCache() = default; //私有构造
    static CentralCache _cacheInstance; // 单例的对象
    SpanList _spanLists[NFREE_LIST]; // hash筒
};


